wayland: Prevent stale paints and weird artifacts when using Weston
authorJasper St. Pierre <jstpierre@mecheye.net>
Fri, 20 Jun 2014 12:55:19 +0000 (08:55 -0400)
committerJasper St. Pierre <jstpierre@mecheye.net>
Fri, 20 Jun 2014 13:02:02 +0000 (09:02 -0400)
Weston releases buffers almost immediately after they're done, which
means that GTK+ doesn't use a temporary surface and instead paints
directly onto the SHM backing store that Weston will use.

Normally, after painting to the temporary surface, GTK+ *replaces*
the existing backing surface with CAIRO_OPERATOR_SOURCE. However,
if we immediately paint to the backing surface, it might have junk
from the last paint in it. So clear out the backing surface whenever
somebody calls begin_paint_region().

Maybe we should just always use the temporary surface like the X11
codepath, since that prevents us from having to do weird things like
this, but oh well.

gdk/wayland/gdkdisplay-wayland.c
gdk/wayland/gdkprivate-wayland.h
gdk/wayland/gdkwindow-wayland.c

index ee8e903f388b45be276f8921885dbca78d2d69f2..d83d364f48cf151e69899af506cebd082f76f690 100644 (file)
@@ -889,3 +889,10 @@ _gdk_wayland_shm_surface_get_busy (cairo_surface_t *surface)
   GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key);
   return data->busy;
 }
+
+void
+_gdk_wayland_shm_surface_clear (cairo_surface_t *surface)
+{
+  GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key);
+  memset (data->buf, 0, data->buf_length);
+}
index d6d2375429c33f357d13a9a7f71afe65472aea58..a3146ead960aac5bf7989068075264b2db813a4e 100644 (file)
@@ -185,5 +185,6 @@ cairo_surface_t * _gdk_wayland_display_create_shm_surface (GdkWaylandDisplay *di
 struct wl_buffer *_gdk_wayland_shm_surface_get_wl_buffer (cairo_surface_t *surface);
 void _gdk_wayland_shm_surface_set_busy (cairo_surface_t *surface);
 gboolean _gdk_wayland_shm_surface_get_busy (cairo_surface_t *surface);
+void _gdk_wayland_shm_surface_clear (cairo_surface_t *surface);
 
 #endif /* __GDK_PRIVATE_WAYLAND_H__ */
index 745deb9f676deeecef9a3e802088f6d5d2bd0c89..461d1ce9d78b6fb6ce5f8fd1732895a4f47da17a 100644 (file)
@@ -568,7 +568,23 @@ gdk_window_impl_wayland_begin_paint_region (GdkWindow            *window,
 {
   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
   gdk_wayland_window_ensure_cairo_surface (window);
-  return _gdk_wayland_shm_surface_get_busy (impl->cairo_surface);
+
+  if (_gdk_wayland_shm_surface_get_busy (impl->cairo_surface))
+    {
+      /* The surface is busy, so create a temporary surface which we paint
+       * to and hope that by the time we're done painting the surface isn't
+       * busy any more. */
+      return TRUE;
+    }
+  else
+    {
+      /* Returning FALSE from begin_paint_region says to use the native
+       * backing surface, which is our SHM surface. We need to make sure
+       * to clear it before the code tries to paint to it to prevent
+       * artifacts from the last paint. */
+      _gdk_wayland_shm_surface_clear (impl->cairo_surface);
+      return FALSE;
+    }
 }
 
 static void